package cn.com.iscs.sqlProject.util;

import cn.com.iscs.sqlProject.entity.SyNextNumber;
import cn.com.iscs.sqlProject.mapper.SyNextNumberMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.ResultSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class UKID implements java.io.Serializable {
	private static final Log logger = LogFactory.getLog(UKID.class);

	private static Lock lock = new ReentrantLock();
	private static int[] counterArr = new int[10];
	private static String appSecret;
	private static String addr;
	private static String[] jvmidArr = new String[10];
	private static String[] daysArr = new String[10];
	private static int jvm_length;
	private static int once_count = 999;

	static {
		JdbcUtil jdbc = new JdbcUtil();
		try {
			ResultSet rs = jdbc.executeQuery("select app_secret from sy_constant");
			if (rs.first()) {
				appSecret = rs.getString("app_secret");
				//第1版本,暂不用版本号
		        /*
                String ver = appSecret.substring(2, 3);
                int l = Integer.parseInt(appSecret.substring(3, 4));
                if ("1".equals(ver)) {
                    addr = appSecret.substring(4, 4 + l);
                } else {
                    addr = ver + appSecret.substring(4, 4 + l);
                }*/
				addr = appSecret.substring(5, 6);
				jvm_length = Integer.parseInt(appSecret.substring(13, 14));
			} else {
				throw new Exception("Not config SY_CONSTANT app_secret.");
			}
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			jdbc.close();
		}
		for (int i = 0; i < 10; i++) {
			calcJvmId(i);
		}
	}

	private static void calcJvmId(int item) {
		try {
			SyNextNumberMapper syNextNumberMapper = (SyNextNumberMapper) SpringUtil.getBean("syNextNumberMapper");
			SyNextNumber nn = new SyNextNumber();
			nn.setNumberType("XU" + item);
			syNextNumberMapper.getNextNumber(nn);
			String no = nn.getReturnNo();
			String date = no.substring(4, 10);
			no = no.substring(no.length() - 8);
			daysArr[item] = StringUtils.lpad(String.valueOf(DateUtil.getDay(date)), 4, "0");
			jvmidArr[item] = StringUtils.lpad(String.valueOf(Integer.parseInt(no)), jvm_length, "0");
		} catch (NumberFormatException e) {
			logger.error("calcJvmId faild ", e);
			e.printStackTrace();
		}
	}

	protected static int getCount(int item) {
		lock.lock();
		try {
			if (counterArr[item] > once_count) {// 如果超过once_count，则重新取
				counterArr[item] = 0;
				calcJvmId(item);
			}
			if (StringUtils.isEmpty(jvmidArr[item])) {
				calcJvmId(item);
			}
			return counterArr[item]++;
		} finally {
			lock.unlock();
		}
	}

	@Transactional(value = "transactionUkidManager", propagation = Propagation.NEVER, rollbackFor = Exception.class)
	public final static Long getUKID() throws Exception {
		int item = (int) (Math.random() * 10);
		if (jvmidArr[item].length() > jvm_length) {
			throw new Exception("计算UKID出错，超过最大值: " + jvmidArr[item] + "   " + jvm_length);
		}
		int count = getCount(item);
		int onceLength = String.valueOf(once_count).length();
		String ukid = addr + daysArr[item] + item + jvmidArr[item] + StringUtils.lpad(String.valueOf(count), onceLength, "0");
		return Long.valueOf(ukid);
	}


}
